Use the common pointer grab code instead of tracking it ourselves
authorRichard Hult <richard@imendio.com>
Mon, 2 Feb 2009 13:11:46 +0000 (14:11 +0100)
committerAlexander Larsson <alex@localhost.localdomain>
Thu, 2 Apr 2009 08:15:31 +0000 (10:15 +0200)
gdk/quartz/gdkevents-quartz.c
gdk/quartz/gdkwindow-quartz.c

index 3a8d32420d25b61a788ff074e1fef93045e67368..03e2256236091bf2f0bbb9a386d48bdd55cc1ae3 100644 (file)
@@ -39,11 +39,6 @@ static GdkWindow   *current_mouse_window;
 /* This is the window corresponding to the key window */
 static GdkWindow   *current_keyboard_window;
 
-/* This is the pointer grab window */
-GdkWindow          *_gdk_quartz_pointer_grab_window;
-static gboolean     pointer_grab_owner_events;
-static GdkEventMask pointer_grab_event_mask;
-
 /* This is the keyboard grab window */
 GdkWindow *         _gdk_quartz_keyboard_grab_window;
 static gboolean     keyboard_grab_owner_events;
@@ -185,42 +180,11 @@ gdk_display_keyboard_ungrab (GdkDisplay *display,
   _gdk_quartz_keyboard_grab_window = NULL;
 }
 
-static void
-pointer_ungrab_internal (void)
-{
-  if (!_gdk_quartz_pointer_grab_window)
-    return;
-
-  g_object_unref (_gdk_quartz_pointer_grab_window);
-  _gdk_quartz_pointer_grab_window = NULL;
-
-  pointer_grab_owner_events = FALSE;
-  pointer_grab_event_mask = 0;
-
-  /* FIXME: Send crossing events */
-}
-
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
                            guint32     time)
 {
-  pointer_ungrab_internal ();
-}
-
-static GdkGrabStatus
-pointer_grab_internal (GdkWindow    *window,
-                      gboolean      owner_events,
-                      GdkEventMask  event_mask,
-                      GdkWindow    *confine_to,
-                      GdkCursor    *cursor)
-{
-  /* FIXME: Send crossing events */
-  
-  _gdk_quartz_pointer_grab_window = g_object_ref (window);
-  pointer_grab_owner_events = owner_events;
-  pointer_grab_event_mask = event_mask;
-
-  return GDK_GRAB_SUCCESS;
+  _gdk_display_unset_has_pointer_grab (display, FALSE, FALSE, time);
 }
 
 GdkGrabStatus
@@ -238,31 +202,22 @@ gdk_pointer_grab (GdkWindow    *window,
 
   toplevel = gdk_window_get_toplevel (window);
 
-  /* TODO: What do we do for offscreens and their children? We need to proxy the grab somehow */
-  if (!GDK_IS_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl))
-    return GDK_GRAB_SUCCESS;
-
-  if (_gdk_quartz_pointer_grab_window)
-    {
-      if (_gdk_quartz_pointer_grab_window != window)
-        generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
-                                    FALSE,
-                                    window);
-
-      pointer_ungrab_internal ();
-    }
+  _gdk_display_set_has_pointer_grab (_gdk_display,
+                                     window,
+                                     toplevel,
+                                     owner_events,
+                                     event_mask,
+                                     0,
+                                     time,
+                                     FALSE);
 
-  return pointer_grab_internal (window, owner_events, event_mask, 
-                               confine_to, cursor);
+  return GDK_GRAB_SUCCESS;
 }
 
-/* This is used to break any grabs in the case where we have to due to
- * the grab emulation. Instead of enforcing the desktop wide grab, we
- * break it when the app loses focus for example.
- */
 static void
-break_all_grabs (void)
+break_all_grabs (guint32 time)
 {
+  /*
   if (_gdk_quartz_keyboard_grab_window)
     {
       generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
@@ -271,13 +226,14 @@ break_all_grabs (void)
       g_object_unref (_gdk_quartz_keyboard_grab_window);
       _gdk_quartz_keyboard_grab_window = NULL;
     }
-
-  if (_gdk_quartz_pointer_grab_window)
+  */
+  if (_gdk_display->pointer_grab.window)
     {
-      generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
-                                  FALSE,
-                                  NULL);
-      pointer_ungrab_internal ();
+      g_print ("break all grabs\n");
+      _gdk_display_unset_has_pointer_grab (_gdk_display,
+                                           _gdk_display->pointer_grab.implicit,
+                                           FALSE,
+                                           time);
     }
 }
 
@@ -323,37 +279,6 @@ gdk_event_apply_filters (NSEvent *nsevent,
   return GDK_FILTER_CONTINUE;
 }
 
-/* Checks if the passed in window is interested in the event mask, and
- * if so, it's returned. If not, the event can be propagated through
- * its ancestors until one with the right event mask is found, up to
- * the nearest toplevel.
- */
-static GdkWindow *
-find_window_interested_in_event_mask (GdkWindow    *window, 
-                                     GdkEventMask  event_mask,
-                                     gboolean      propagate)
-{
-  GdkWindowObject *private;
-
-  private = GDK_WINDOW_OBJECT (window);
-  while (private)
-    {
-      if (private->event_mask & event_mask)
-       return (GdkWindow *)private;
-
-      if (!propagate)
-       return NULL;
-
-      /* Don't traverse beyond toplevels. */
-      if (GDK_WINDOW_TYPE (private) != GDK_WINDOW_CHILD)
-       break;
-
-      private = private->parent;
-    }
-
-  return NULL;
-}
-
 static guint32
 get_time_from_ns_event (NSEvent *event)
 {
@@ -569,8 +494,8 @@ _gdk_quartz_events_get_mouse_window (gboolean consider_grabs)
   if (!consider_grabs)
     return current_mouse_window;
 
-  if (_gdk_quartz_pointer_grab_window && !pointer_grab_owner_events)
-    return _gdk_quartz_pointer_grab_window;
+  if (_gdk_display->pointer_grab.window && !_gdk_display->pointer_grab.owner_events)
+    return _gdk_display->pointer_grab.window;
   
   return current_mouse_window;
 }
@@ -724,65 +649,6 @@ get_converted_window_coordinates (GdkWindow *in_window,
                                        out_x, out_y);
 }
 
-/* Given a mouse NSEvent (must be a mouse event for a GDK window),
- * finds the subwindow over which the pointer is located. Returns
- * coordinates relative to the found window. If no window is found,
- * returns the root window, and root window coordinates.
- */
-static GdkWindow *
-find_mouse_window_for_ns_event (NSEvent *nsevent,
-                                gint    *x_ret,
-                                gint    *y_ret)
-{
-  GdkWindow *event_toplevel;
-  GdkWindowImplQuartz *impl;
-  GdkWindowObject *private;
-  GdkWindow *mouse_toplevel;
-  GdkWindow *mouse_window;
-  NSPoint point;
-  gint x_tmp, y_tmp;
-
-  event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
-  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
-  private = GDK_WINDOW_OBJECT (event_toplevel);
-  point = [nsevent locationInWindow];
-
-  x_tmp = point.x;
-  y_tmp = private->height - point.y;
-
-  mouse_toplevel = gdk_window_get_toplevel (current_mouse_window);
-
-  get_converted_window_coordinates (event_toplevel,
-                                    x_tmp, y_tmp,
-                                    mouse_toplevel,
-                                    &x_tmp, &y_tmp);
-
-  mouse_window = _gdk_quartz_window_find_child (mouse_toplevel, x_tmp, y_tmp);
-  if (mouse_window && mouse_window != mouse_toplevel)
-    {
-      get_child_coordinates_from_ancestor (mouse_toplevel,
-                                           x_tmp, y_tmp,
-                                           mouse_window,
-                                           &x_tmp, &y_tmp);
-    }
-  else if (!mouse_window)
-    {
-      /* This happens for events on the window title buttons and the
-       * desktop, treat those as being on the root window.
-       */
-      get_converted_window_coordinates (mouse_toplevel,
-                                        x_tmp, y_tmp,
-                                        _gdk_root,
-                                        &x_tmp, &y_tmp);
-      mouse_window = _gdk_root;
-    }
-
-  *x_ret = x_tmp;
-  *y_ret = y_tmp;
-
-  return mouse_window;
-}
-
 /* Trigger crossing events if necessary. This is used when showing a new
  * window, since the tracking rect API doesn't work reliably when a window
  * shows up under the mouse cursor. It's done by finding the topmost window
@@ -921,9 +787,9 @@ find_window_for_ns_event (NSEvent *nsevent,
     case NSRightMouseDragged:
     case NSOtherMouseDragged:
       {
-       GdkWindow *mouse_window;
-       GdkEventMask event_mask;
-       GdkWindow *real_window;
+       GdkDisplay *display;
+
+        display = gdk_drawable_get_display (toplevel);
 
        /* From the docs for XGrabPointer:
         *
@@ -937,49 +803,36 @@ find_window_for_ns_event (NSEvent *nsevent,
         * This means we first try the owner, then the grab window,
         * then give up.
         */
-       if (0 && _gdk_quartz_pointer_grab_window) /* FIXME: Implement grabs? */
+       if (display->pointer_grab.window)
          {
-           if (pointer_grab_owner_events)
-             {
-                mouse_window = find_mouse_window_for_ns_event (nsevent, x, y);
-               event_mask = get_event_mask_from_ns_event (nsevent);
-               real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
-               
-               if (mouse_window && real_window && mouse_window != real_window)
-                 get_ancestor_coordinates_from_child (mouse_window,
-                                                      *x, *y,
-                                                      real_window,
-                                                      x, y);
-
-               if (real_window)
-                 return real_window;
-             }
+           if (display->pointer_grab.owner_events)
+              return toplevel;
 
            /* Finally check the grab window. */
-           if (pointer_grab_event_mask & get_event_mask_from_ns_event (nsevent))
+           if (display->pointer_grab.event_mask & get_event_mask_from_ns_event (nsevent))
              {
-                GdkWindow *event_toplevel;
                GdkWindow *grab_toplevel;
                NSPoint point;
                int x_tmp, y_tmp;
 
-                event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
-               grab_toplevel = gdk_window_get_toplevel (_gdk_quartz_pointer_grab_window);
+               grab_toplevel = gdk_window_get_toplevel (display->pointer_grab.window);
                point = [nsevent locationInWindow];
 
                x_tmp = point.x;
                y_tmp = GDK_WINDOW_OBJECT (grab_toplevel)->height - point.y;
 
+                /* FIXME: Would be better and easier to use cocoa to convert. */
+
                 /* Translate the coordinates so they are relative to
                  * the grab window instead of the event toplevel for
                  * the cases where they are not the same.
                  */
-                get_converted_window_coordinates (event_toplevel,
+                get_converted_window_coordinates (toplevel,
                                                   x_tmp, y_tmp,
-                                                  _gdk_quartz_pointer_grab_window,
+                                                  grab_toplevel,
                                                   x, y);
 
-               return _gdk_quartz_pointer_grab_window;
+               return grab_toplevel;
              }
 
            return NULL;
@@ -1009,6 +862,7 @@ find_window_for_ns_event (NSEvent *nsevent,
     case NSKeyUp:
     case NSFlagsChanged:
       {
+        /* FIXME: Use common code here instead. */
        if (_gdk_quartz_keyboard_grab_window && !keyboard_grab_owner_events)
          return _gdk_quartz_keyboard_grab_window;
 
@@ -1428,7 +1282,7 @@ gdk_event_translate (GdkEvent *event,
   if (event_type == NSAppKitDefined)
     {
       if ([nsevent subtype] == NSApplicationDeactivatedEventType)
-        break_all_grabs ();
+        break_all_grabs (get_time_from_ns_event (nsevent));
 
       /* This could potentially be used to break grabs when clicking
        * on the title. The subtype 20 is undocumented so it's probably
@@ -1492,7 +1346,7 @@ gdk_event_translate (GdkEvent *event,
    */
   if ([(GdkQuartzWindow *)nswindow isInMove])
     {
-      break_all_grabs ();
+      break_all_grabs (get_time_from_ns_event (nsevent));
       return FALSE;
     }
 
index c91d06a3e375919b8140ee775fc34837e38a60e8..66a488df5f76c00991b7df38d5529748445ae3e3 100644 (file)
@@ -953,7 +953,7 @@ _gdk_quartz_window_destroy (GdkWindow *window,
   /* If the destroyed window was targeted for a pointer or keyboard
    * grab, release the grab.
    */
-  if (window == _gdk_quartz_pointer_grab_window)
+  if (window == _gdk_display->pointer_grab.window)
     gdk_pointer_ungrab (0);
 
   if (window == _gdk_quartz_keyboard_grab_window)
@@ -1122,7 +1122,7 @@ gdk_window_quartz_hide (GdkWindow *window)
       [impl->view setHidden:YES];
     }
 
-  if (window == _gdk_quartz_pointer_grab_window)
+  if (window == _gdk_display->pointer_grab.window)
     gdk_pointer_ungrab (0);
 
   if (window == _gdk_quartz_keyboard_grab_window)
@@ -1788,7 +1788,7 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
       x_tmp = point.x;
       y_tmp = private->height - point.y;
 
-      window = toplevel;
+      window = (GdkWindow *)toplevel;
     }
 
   found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp);